package org.jmc.refmanager.domain.service;

import java.util.List;
import java.util.Set;

import org.jmc.refmanager.domain.dao.QueryParam;
import org.jmc.refmanager.domain.model.OrgUnit;
import org.jmc.refmanager.domain.model.Role;
import org.jmc.refmanager.domain.model.User;

public interface UserManager {
	/**
	 * Persist a User entity in the database
	 * 
	 * @param transientUser
	 */
	public void persist(User transientUser);

	/**
	 * Remove a persisted User from the database
	 * 
	 * @param persistentUser
	 */
	public void remove(User persistentUser);

	/**
	 * 
	 * @param userId
	 */
	public void remove(Integer userId);
	
	/**
	 * Update a User in the database
	 * 
	 * @param detachedUser
	 * @return merged User
	 */
	public User update(User detachedUser);

	/**
	 * Find a User by id
	 * 
	 * @param id
	 * @return the found User
	 */
	public User findById(Integer id);

	/**
	 * Recherche un utilisateur par matricule
	 * 
	 * @param matricule
	 * @return the found User
	 */
	public User getByMatricule(String matricule);

	/**
	 * Find all User
	 * 
	 * @return the found User
	 */
	public List<User> findAll();

	/**
	 * Liste les utilisateurs du systeme de maniere paginee.
	 * Le filtre de securite s'applique:
	 * - si l'utilisateur connecte est un approbateur, 
	 * alors seuls les utilisateurs de son equipe sont retournes
	 * - si l'utilisateur est un administrateur, tous les utilisateurs sont retournes
	 * - sinon aucun utilisateur n'est retourne
	 * 
	 * @param first index de debut de page
	 * @param count nombre d'element par page
	 * @param sortPropertyName
	 * @param sortAscendingOrder
	 * 
	 * @return la liste des utilisateurs du systeme. 
	 * Le nombre d'utilisateurs retournes est au plus egal e <code>count</code>.
	 */
	public List<User> list(QueryParam queryParam);

	/**
	 * Compte le nombre d'utilisateurs (meme requete que list ci-dessus)
	 * @return
	 */
	public Integer count();

	/**
	 * Liste les utilisateurs du systeme de maniere paginee.
	 * Le filtre de securite s'applique:
	 * - si l'utilisateur connecte est un approbateur, 
	 * alors seuls les utilisateurs de son equipe sont retournes
	 * - si l'utilisateur est un administrateur, tous les utilisateurs sont retournes
	 * - sinon aucun utilisateur n'est retourne
	 * 
	 * @param first index de debut de page
	 * @param count nombre d'element par page
	 * @param sortPropertyName
	 * @param sortAscendingOrder
	 * 
	 * @return la liste des utilisateurs du systeme. 
	 * Le nombre d'utilisateurs retournes est au plus egal e <code>count</code>.
	 */
	public List<User> listByMatricule(QueryParam queryParam, String matricule);

	/**
	 * Compte le nombre d'utilisateurs en precisant la requete
	 * @return
	 */
	public Integer countByMatricule(String matricule);
	
	
	/**
	 * Recherche une liste de referents pouvant valider le service.
	 * 
	 * @param service le service necessitant une validation
	 * 
	 * @return une liste de referent. Si aucun referent ne
	 * peut etre trouve alors le referent est l'administrateur. 
	 */
	public Set<User> findApproversOfService(OrgUnit service);

	/**
	 * Recherche une liste de referents de la direction.
	 * 
	 * @param direction la direction
	 * 
	 * @return une liste de referents. Si aucun referent ne
	 * peut etre trouve alors le referent est l'administrateur ? 
	 */
	public Set<User> findApproversOfDirection(OrgUnit direction);

	/**
	 * Changement du mot de passe d'un utilisateur
	 * 
	 * @param user l'utilisateur
	 * @param oldPassword L'ancien mot de passe
	 * @param newPassword Le nouveau mot de passe
	 */
	public void changePassword(User user, String oldPassword, String newPassword);
	
	/**
	 * Changement de rele de la personne.
	 * 
	 * Si la personne etait un approbateur, ses teches sont assignees
	 * aux autres approbateurs de la meme portee et la teche est rendue disponible.
	 * 
	 * Si la personne etait un utilisateur, rechercher les teches
	 * lui etant assignables.
	 *  
	 * @param user L'utilisateur
	 * @param newRole le nouveau rele
	 * @param scope le perimetre si la personne est un approbateur
	 */
	public void updateRole(User user, Role newRole, OrgUnit scope);
	
	/**
	 * Mise e jour du perimetre de l'approbateur.
	 * 
	 * Ses teches sont assignees aux autres approbateurs de l'ancienne portee.
	 * Les teches assignables dans sa nouvelle portee sont assignees.
	 * 
	 * Question : que faire des autres users appartenant e son equipe?
	 * 
	 * Cette fonction est reservee e un administrateur.
	 * 
	 * @param approver
	 * @param newScope
	 */
	public void updateScope(User approver, OrgUnit newScope);
}
